// ml:run = $bin < input
// ml:ccf += -g
// ml:opt = 0
#include <iostream>
#include <algorithm>
#include <cstring>

using ll = long long;

struct data
{
    int pos, l, r, opt, type; // type = 0: vertical,  1: hor
};

bool operator<(data const& a, data const& b)
{
    return a.pos < b.pos || (a.pos == b.pos &&
            ((a.type != b.type && ((a.type == 1 && a.opt > 0) || (a.type == 0 && b.opt < 0))) ||
             (a.type == b.type && a.l < b.l)));

/*     return a.pos < b.pos || (a.pos == b.pos && (a.type > b.type || (a.type == b.type && */
/*                     (a.opt > b.opt || (a.opt == b.opt && a.l < b.l))))); */
}

int const maxn = 200007;
bool skip[maxn];
int disy[maxn];
int tree[4 * maxn];
int sum[4 * maxn];
int len, tot;
int n;

data da[maxn];

void init()
{
    memset(tree, 0, sizeof(tree));
    memset(sum, 0, sizeof(sum));
    memset(skip, 0, sizeof(skip));
    len = 0;
    tot = 0;
}

void push_up(int id)
{
    tree[id] = tree[id * 2] + tree[id * 2 + 1];
    sum[id] = sum[id * 2] + sum[id * 2 + 1];
}

int query(int id, int l, int r, int tl, int tr)
{
    if (tl <= l && r <= tr) {
        return sum[id];
    }
    int mid = (l + r) / 2;
    int ret = 0;
    if (tl <= mid) ret += query(id * 2, l, mid, tl, tr);
    if (tr > mid) ret += query(id * 2 + 1, mid + 1, r, tl, tr);
    return ret;
}

void update(int id, int l, int r, int tl, int d)
{
    if (tl == l && tl == r) {
        tree[id] += d;
        sum[id] = tree[id] > 0;
        return;
    }
    int mid = (l + r) / 2;
    if (tl <= mid) update(id * 2, l, mid, tl, d);
    else update(id * 2 + 1, mid + 1, r, tl, d);
    push_up(id);
}

int main()
{
    std::ios_base::sync_with_stdio(false);
    int T; std::cin >> T;
    while (T--) {
        std::cin >> n;
        init();
        for (int i = 0, x1, y1, x2, y2; i < n; i++) {
            std::cin >> x1 >> y1 >> x2 >> y2;
            if (x1 == x2) {
                da[tot++] = {x1, std::min(y1, y2), std::max(y1, y2), 0, 0};
                disy[len++] = y1;
                disy[len++] = y2;
            } else {
                int tx1 = std::min(x1, x2);
                int tx2 = std::max(x1, x2);
                da[tot++] = {tx1, y1, y1, +1, 1};
                da[tot++] = {tx2, y1, y1, -1, 1};
                disy[len++] = y1;
            }
        }
        std::sort(disy, disy + len);
        len = std::unique(disy, disy + len) - disy;

        std::sort(da, da + tot);
        ll ans = 0;
        for (int i = 1; i < tot; i++) {
            if (da[i].type != 0) continue;
            if (da[i - 1].type != 0) continue;
            if (da[i - 1].pos != da[i].pos) continue;
            if (da[i - 1].r >= da[i].l) {
                da[i].l = da[i - 1].l;
                skip[i - 1] = true;
            }
        }
        for (int i = 0; i < tot; i++) {
            /* std::cout << i << " " << da[i].type << " " << da[i].pos << " " << da[i].l << "\n"; */
            if (skip[i]) continue;
            if (da[i].type == 1) {
                int l = std::lower_bound(disy, disy + len, da[i].l) - disy;
                update(1, 0, len - 1, l, da[i].opt);
            } else {
                int l = std::lower_bound(disy, disy + len, da[i].l) - disy;
                int r = std::lower_bound(disy, disy + len, da[i].r) - disy;
                ans += query(1, 0, len - 1, l, r);
            }
        }
        std::cout << ans << "\n";
    }
}

